import os 
import ctypes  # 新增导入

#改变控制台背景色和字体色
os.system("COLOR 02")
os.system("mode con cols=150 lines=50")
# 设置控制台窗口标题为当前文件名
ctypes.windll.kernel32.SetConsoleTitleW("SMA_Stp05.py - 程序化移动止损程序")  # 使用Windows API设置标题

print("****************************************|                        |****************************************")
print("****************************************|    程序化移动止损程序  |****************************************")
print("****************************************|                        |****************************************")
print("")
print("")
# import taichi as ti
# 获取当前账户持仓信息
from tqsdk import TqKq,TqApi, TqAuth, TqAccount,TargetPosTask
import time
#from tqsdk.ta import MA,EMA
from MyTT import *
# from colorama import init, Fore, Back, Style
import colorama
# init(autoreset=True)
# import MyFun01

#全局变量
mySymbol="CZCE.SA509"
# tqacc = TqAccount("H华安期货", "866035", "szstock888")
# api = TqApi(account=tqacc, auth=TqAuth("szlwy68", "alibaba"),web_gui=":5050")

#使用模拟账号测试
# tqacc = TqAccount("simnow", "097977", "alibaba777")
# api = TqApi(account=tqacc, auth=TqAuth("cps168", "alibaba999"))

#使用快期模拟账户
#api = TqApi(auth=TqAuth("cps168", "alibaba999"))
tq_kq = TqKq()
api = TqApi(account=tq_kq, auth=TqAuth("cps168", "alibaba999"),web_gui=":5050",debug=False)


myacc=api.get_account()

position=api.get_position(mySymbol)

for k,v in position.items(): # k是品种代码，v是position对象
    #print(str(k),str(v.pos),str(v.float_profit)) 
    if k==mySymbol and v.pos>0:
         print(Style.BRIGHT + Back.BLUE + Fore.RED+"Line29","持有纯碱", v.pos+Back.RESET+Fore.RESET+ Style.RESET_ALL) 
         print(str(k),str(v.pos),str(v.float_profit)) 
    else:
        pass

#获取K线数据
klines=api.get_kline_serial(mySymbol,60,data_length=300)
myOpen=klines.iloc[:].open.values
myClose=klines.iloc[:].close.values
myHigh=klines.iloc[:].high.values
myLow=klines.iloc[:].low.values

#计算cpx的值
cpx_list=[]
myQ=0
myQList=[]
#生成Q列表
for x in range(300):
    myQ=(3*myClose[-1-x]+myOpen[-1-x]+myHigh[-1-x]+myLow[-1-x])/6
    myQList.append(myQ)  
myQList.reverse()

#对Q列表进行处理，求出myCpx，并组成列表cpx_list
for y in range(300):
    myCpx=0
    for z in range(26):
        myCpx=myCpx+((26-z)*myQList[-1-y])
    myCpx=myCpx/351
    cpx_list.append(myCpx)

#反转列表，使之存储的数据与对应的K线顺序一致
cpx_list.reverse()
#先对列表取整
for i in range(300):
    cpx_list[i]=round(cpx_list[i],2)
#print(cpx_list)

# 初始化 colorama 库
colorama.init()
def print_info(msg: str):
    print(colorama.Style.BRIGHT+colorama.Back.BLUE+colorama.Fore.RED + str(msg) + colorama.Style.RESET_ALL)
def print_waring(msg: str):
    print(colorama.Style.BRIGHT+colorama.Back.BLUE+colorama.Fore.RED + str(msg) + colorama.Style.RESET_ALL)
def print_error(msg):
    print(colorama.Style.BRIGHT+colorama.Back.BLUE+colorama.Fore.YELLOW + str(msg) + colorama.Style.RESET_ALL)


def write_txt01(msg):    
    try:
        file = open(r"./orders_log.txt", "r+")
        msg=str(msg)
        lines=file.readlines()
        lines.insert(0,msg)
        # file.close()
        # file = open(r"./orders_log.txt", "r+")
        file.writelines(lines)
    finally:
        file.close()

def write_txt02(msg):
    try:
        msg=str(msg)
        with open(r"./orders_log.txt", 'r+',encoding='utf-8') as f:
            content=f.read()
            f.seek(0, 0)
            f.write(msg+"\n"+content)
    finally:
        f.close()

#追加到文件末尾
def write_txt03(msg):
    msg=str(msg)
    with open(r"./orders_log.txt", "a") as fw:
        fw.write(txtmsg)
        fw.write("\n")
#while 循环
while True:
    #副图中画线
    # 将画图代码放在循环中即可使图像随着行情推进而更新
    mySMA27 = SMA(cpx_list, 27)  # 使用MyTT或者tqsdk自带指标函数计算均线
    # 在幅图画两根线，即cpx和mySMA27
    klines["ma_B2"] = cpx_list
    klines["ma_B3"] = mySMA27
    klines["ma_B3.board"] = "B2" 
    klines["ma_B2.board"] = "B2"  # 设置附图: 可以设置任意字符串,同一字符串表示同一副图
    klines["ma_B2.color"] = "green"  # 设置为绿色. 以下设置颜色方式都可行: "green", "#00FF00", "rgb(0,255,0)", "rgba(0,125,0,0.5)"
    #api.draw_line(klines, -10, klines.iloc[-10].low, -3, klines.iloc[-3].high, id="my_line", board="B2", line_type="SEG",color=0xFFFF00FF, width=3)
    klines["ma_B2.width"] = 1 
    klines["ma_B3.width"] = 1 
    if position.pos_long>0 or position.pos_short>0:
        #print("Line82","持有纯碱",position.instrument_id)
        try:
            if position.pos_long>0 or position.pos_short>0:# 止盈不止损，只有盈利大于200的单子才移动止损 and position.float_profit>200:
            #print("持有纯碱") 
                #如果持有多单，但是cpx前值<mySMA27的前值，即处于做空阶段，平全部多单
                if position.pos_long>0 and myClose[-2]<mySMA27[-2]: #前一收盘价，小于mySMA27则平掉持有的多单
                    order = api.insert_order(symbol=mySymbol, direction='SELL', offset='CLOSE', volume=position.pos_long)
                    msg="\n"+"品种："+position.instrument_id+" info:"+"多单止损"+" 时间："+time.strftime("%Y-%m-%d %H:%M:%S")+"\n"
                    print_waring(msg)
                    txtmsg="品种："+position.instrument_id+" info:"+"多单止损"+" 时间："+time.strftime("%Y-%m-%d %H:%M:%S")
                    write_txt03(txtmsg)
                    write_txt02(msg)

                #如果持有空单，但是cpx前值大于mySMA27的前值，即处于做多阶段，平全部空单
                if position.pos_short>0 and myClose[-2]>mySMA27[-2]:#前一收盘价，大于mySMA27则平掉持有的空单
                    order = api.insert_order(symbol=mySymbol, direction='BUY', offset='CLOSE', volume=position.pos_short)
                    msg="\n"+"品种："+position.instrument_id+" info:"+"空单止损"+" 时间："+time.strftime("%Y-%m-%d %H:%M:%S")+"\n"
                    print_waring(msg)
                    txtmsg="品种："+position.instrument_id+" info:"+"空单止损"+" 时间："+time.strftime("%Y-%m-%d %H:%M:%S")
                    write_txt03(txtmsg)
                    write_txt02(msg)
                    
            else:
                msg="持仓为 0 "
                print_waring(msg)
        except Exception as e:
            #raise e
            pass

    #*****************************************
    deadline = time.time() + 1
    # while api.wait_update(deadline=deadline):  # 等待3秒
    #     pass
    api.wait_update(deadline=deadline)    
